<template>
  <div>
    <r-table
      ref="rTable"
      @onLoadData="handleOnLoadData"
      :option="tableOption"
    >
      <div slot="toolBar" style="margin-bottom: 10px;" class="space-between">
        <div class="flex">
          <div class="flex-con">
            <template v-for="(item,itemIndex) in toolButtons">
              <el-button
                v-if="item.buttonFuncType === ButtonFuncTypeEnum.NORMAL"
                :key="itemIndex"
                v-perm="item.name"
                class="filter-item"
                :type="getButtonType(item)"
                size="mini"
                @click="handleClickToolButton(item)"
              >
                {{ item.label }}
              </el-button>
              <file-uploader
                v-else-if="item.buttonFuncType === ButtonFuncTypeEnum.UPLOAD_FILE"
                :key="itemIndex"
                v-perm="item.name"
                class="filter-item"
                style="display: inline-block"
                :action="item.funcOption.action"
                :type="getButtonType(item)"
                size="mini"
                @success="reloadTable"
              >
                {{ item.label }}
              </file-uploader>
            </template>
          </div>
          <div>
            <template v-for="(item,itemIndex) in toolButtonsRight">
              <el-button
                v-if="item.buttonFuncType === ButtonFuncTypeEnum.NORMAL"
                :key="itemIndex"
                v-perm="item.name"
                class="filter-item"
                :type="getButtonType(item)"
                size="mini"
                @click="handleClickToolButton(item)"
              >
                {{ item.label }}
              </el-button>
              <file-uploader
                v-else-if="item.buttonFuncType === ButtonFuncTypeEnum.UPLOAD_FILE"
                :key="itemIndex"
                v-perm="item.name"
                class="filter-item"
                style="display: inline-block"
                :action="item.funcOption.action"
                :type="getButtonType(item)"
                size="mini"
                @success="reloadTable"
              >
                {{ item.label }}
              </file-uploader>
            </template>
            <el-button size="mini" @click="handleShowColSelect" v-if="tableOption.columnSelector">
              列筛选
            </el-button>
            <el-button size="mini" @click="handleToggleCollapse" v-if="rowButtons.length">
              <span v-if="opShowed">
              收起 &gt;&gt;
              </span>
              <span v-else>
              展开 &lt;&lt;
              </span>
            </el-button>
          </div>
        </div>
      </div>
      <el-table-column
        align="left"
        label="操作"
        slot="column"
        :width="tableOption.opWidth||200"
        :fixed="opFixed"
        v-if="rowButtons.length && opShowed"
        class-name="small-padding"
      >
        <template slot-scope="scope">
          <div class="column-button-area">
            <template v-for="(item,itemIndex) in rowButtons">
              <el-button
                v-if="isButtonShowed(scope.row,item)"
                :key="itemIndex"
                class="column-button"
                type="text"
                size="mini"
                v-perm="item.name"
                @click="handleClickToolButton(item,scope.row)"
              >
                {{ item.label }}
              </el-button>
            </template>
          </div>
        </template>
      </el-table-column>
    </r-table>
    <dialog-columns-form
      v-model="formData"
      :lang="tableOption.lang"
      :width="tableOption.dialogWidth"
      :label-width="tableOption.formLabelWidth"
      :show-continue="!isEdit"
      :group-id="tableOption.groupId"
      :is-edit="isEdit"
      ref="dialogForm"
      :title="isEdit?tableOption.title.edit:tableOption.title.add"
      :loading="dialogLoading"
      :visible.sync="dialogShowed"
      :columns="tableOption.columns"
      @submit="handleSubmit"
      @submitAndContinue="handleSubmitAndContinue"
    />
    <dialog-columns-form
      v-model="formData"
      :lang="tableOption.lang"
      :width="tableOption.dialogWidth"
      :group-id="tableOption.groupId"
      :is-edit="isEdit"
      view-mode
      ref="viewDialog"
      title="详情"
      :loading="dialogLoading"
      :visible.sync="viewDialogShowed"
      :columns="tableOption.columns"
    />
    <dialog-columns-form
      v-model="formData"
      width="600px"
      ref="dialogFormForSort"
      :group-id="tableOption.groupId"
      title="修改排序"
      :loading="dialogLoading"
      :visible.sync="setSortNumDialogShowed"
      :columns="setSortNumColumns"
      @submit="handleSetSortNum"
    />
    <col-selector :visible.sync="colSelectDialogShowed" :option="tableOption" :visible-map.sync="unVisibleFieldMap"/>
  </div>
</template>

<script>
import RTable from '@/framework/components/table/RTable'
import TableButtonType from '@/framework/constant/TableButtonType'
import BaseTableService from '@/framework/infra/base/BaseTableService'
import DialogColumnsForm from '@/framework/components/form/DialogColumnsForm'
import FormUtil from '@/framework/infra/form/FormUtil'
import NameUtil from '@/framework/infra/name/NameUtil'
import DomUtil from '@/framework/infra/util/DomUtil'
import RouterUtil from '@/framework/infra/router/RouterUtil'
import { mapGetters } from 'vuex'
import ButtonFuncTypeEnum from '@/framework/constant/ButtonFuncTypeEnum'
import FileUploader from '@/framework/components/FileUploader'
import ColumnUtil from '@/framework/components/table/ColumnUtil'
import TableSetting from '@/framework/components/table/TableSetting'
import ColSelector from '@/framework/components/table/ColSelector'
import * as db from '@/framework/infra/util/dbUtil'

export default {
  name: 'CURDTable',
  components: { ColSelector, FileUploader, DialogColumnsForm, RTable },
  data() {
    return {
      viewDialogShowed: false,
      dialogShowed: false,
      colSelectDialogShowed: false,
      dialogLoading: false,
      unVisibleFieldMap: db.get('r-table_' + location.hash) || {},
      setSortNumDialogShowed: false,
      formData: null,
      isEdit: false,
      opShowed: db.get('op_showed_' + location.hash, true),
      ButtonFuncTypeEnum
    }
  },
  computed: {
    ...mapGetters(['routes']),
    buttons() {
      return this.tableOption.buttons || RouterUtil.getButtonsByFullPath(this.routes, this.$route.path, this.tableOption.groupId) || []
    },
    toolButtons() {
      return this.buttons.filter(el => el.type === TableButtonType.TOOLBAR)
    },
    toolButtonsRight() {
      return this.buttons.filter(el => el.type === TableButtonType.TOOLBAR_RIGHT)
    },
    rowButtons() {
      return this.buttons.filter(el => el.type === TableButtonType.ROW)
    },
    opFixed() {
      if ('opFixed' in this.tableOption) {
        return this.tableOption.opFixed
      }
      if (ColumnUtil.parseColumns(this.tableOption.columns).length > 5) {
        return 'right'
      }
      return null
    },

    setSortNumColumns() {
      return this.tableOption.columns.filter(el => el.prop === 'sortNum')
    },
    tableOption() {
      const result = Object.assign({}, {
        initFormParams: {},
        serviceClass: BaseTableService,
        columns: [],
        rowKey: 'id',
        pagination: true,
        tab: {
          options: [],
          defaultValue: ''
        },
        loadDetail: false, // 是否加载详情接口
        requestApi: null,
        opWidth: 200,
        buttons: null,
        resetBtn: true,
        columnSelector: true,
        initListParams: {},
        groupId: 0,

        requestApiNames: {
          list: 'list'
        },
        title: {
          edit: '修改',
          add: '新建'
        },
        autoLoad: true,
        dialogWidth: '900px',
        formLabelWidth: '140px',
        lang: false,
        showSelection: true,
        // tableHeight: window.innerHeight - 260 - (this.hasTab ? 160 : 0)
        // tableHeight: window.innerHeight - 260 - (this.hasTab ? 160 : 0)
        tableHeight: 0
      }, this.option)
      // result.columns.forEach(col => {
      //   if (!('_visible' in col)) {
      //     col._visible = db.getField('r-table_' + location.hash, col.prop, true)
      //   } else {
      //     db.setField('r-table_' + location.hash, col.prop, col._visible)
      //   }
      // })
      return result
    }
  },
  methods: {
    handleToggleCollapse() {
      this.opShowed = !this.opShowed
      this.$refs.rTable.doLayout()
    },
    isVisible(el) {
      return el.prop in this.unVisibleFieldMap ? this.unVisibleFieldMap[el.prop] : true
    },
    handleOnLoadData(arg) {
      this.$emit('onLoadData', arg)
    },
    handleShowColSelect() {
      this.colSelectDialogShowed = true
    },
    handleExport(arg) {
      this.$refs.rTable.handleExport(arg)
    },
    emitEvent(eventName, arg) {
      const funcType = NameUtil.camelCase('on', eventName)
      const func = DomUtil.findClosetFuncHandleWithFuncName(this, funcType)
      if (func) {
        func(arg)
        return true
      }
      return false
    },
    reloadTable() {
      this.$refs.rTable.handleList()
    },
    setListParam(key, value) {
      this.$refs.rTable.listParams[key] = value
      return this
    },
    // setApiName(key, value) {
    //
    // },
    setFilterParam(key, value) {
      this.$refs.rTable.filterParams[key] = value
      return this
    },
    clearValidate() {
      this.$refs.dialogForm.clearValidate()
    },
    handleClickToolButton(button, arg) {
      // if (this.service.hasFuncType(button.funcType)) {
      //   return this.service.dispatch(button, arg)
      // }
      // const funcType = NameUtil.camelCase('handle', button.funcType)
      // DomUtil.invokeClosetDomWithFuncName(this, funcType, {$table: this, $service: this.service, arg})
      const funcType = NameUtil.camelCase('handle', button.funcType)
      const func = DomUtil.findClosetFuncHandleWithFuncName(this.$parent, funcType)
      if (func) {
        func({ $table: this, $service: this.service, arg })
      } else {
        if (this.service.hasFuncType(button.funcType)) {
          return this.service.dispatch(button, arg)
        } else {
          if (!this.$refs.rTable[funcType]) {
            alert('无法找到' + funcType)
            return
          }
          this.$refs.rTable[funcType]()
        }
      }
    },
    setInEdit(edit) {
      this.isEdit = edit
    },
    getInitFormData() {
      return FormUtil.createFormDataWithColumns(this.tableOption.columns, this.tableOption.lang || null,
        Object.assign(TableSetting.getDefaultSearchParam(), TableSetting.getDefaultLocalSearchParam())
      )
    },
    isButtonShowed(row, button) {
      return this.service.isButtonShowed(row, button)
    },
    getMultipleSelection() {
      return this.$refs.rTable.multipleSelection
    },
    getButtonType(item) {
      if (item.buttonType) {
        return item.buttonType
      }
      return 'primary'
    },
    hideFormDialog() {
      this.dialogShowed = false
    },
    showFormDialog() {
      this.dialogShowed = true
    },
    showViewDialog() {
      this.viewDialogShowed = true
    },
    hideSetSortNumDialog() {
      this.setSortNumDialogShowed = false
    },
    showSetSortNumDialog(row) {
      FormUtil.fill(this.formData, row)
      this.setSortNumDialogShowed = true
    },
    async handleSubmit({ done }) {
      try {
        await this.service.dispatch({ funcType: 'submitForm' }, this.formData)
      } finally {
        done()
      }
    },
    async handleSubmitAndContinue({ done }) {
      try {
        await this.service.dispatch({ funcType: 'submitFormAndContinue' }, this.formData)
      } finally {
        done()
      }
    },
    async handleSetSortNum({ done }) {
      try {
        await this.service.dispatch({ funcType: 'submitSetSortNum' }, this.formData)
      } finally {
        done()
      }
    }
  },
  created() {
    // eslint-disable-next-line new-cap
    this.service = new this.tableOption.serviceClass(this)
    this.initFormData = this.getInitFormData()
    this.formData = this.getInitFormData()
  },
  watch: {
    unVisibleFieldMap() {
      db.set('r-table_' + location.hash, this.unVisibleFieldMap)
    },
    opShowed() {
      db.set('op_showed_' + location.hash, this.opShowed)
    }
  },
  props: {
    option: {
      type: Object,
      default() {
        return {}
      }
    }
  }
}
</script>

<style scoped lang="scss">
.column-button {
  margin-bottom: 10px;
}

.column-button-area {
  margin-bottom: -10px;
}
</style>
